/**
 * Ewok Poker
 * By Viljar Kärgenberg
 */
const PREFLOPGAME = 0;
const FLOPGAME = 1;
const TURNGAME = 2;
const RIVERGAME = 3;
const SHOWDOWN = 4;
const WINNER = 6;
const SHOWDOWLENGTH = 5000;
var humanPos = 0;
var NEXTPHASE = 0;
var PLAYERNAMES = [ "Lobifo", "Ightend", "Yturu", "Keannper", "Calig",
		"Ight'gare", "War'os", "Rothildo", "Samther", "Garack", "Erk", "Oilde",
		"Tiaiv", "Bryine", "Sadala", "Yerorm", "Quel", "Thertornal",
		"Danworunt", "Emtor", "Ruich", "Navaty", "Alesay", "Mor'cer", "Dehes",
		"Tiathbel", "Ny'kin'eil", "Onndan", "Isnys", "Sudeny", "Tasage",
		"Turuvaro", "Orm'pere", "Ingu", "Pyphan", "Ineas", "Luiptur",
		"Ormoughack", "End'vor", "Essurn", "Imn", "Bansdel", "Emtas", "Darron",
		"Orrany", "Et'ser", "Bavesdan", "Haezkal", "Nozver", "Veban", "Rynique",
		"Alatair", "Dracula", "Frank N Stein", "J.J", "Ace", "Karl XII", "Yoda"];
function startGame() {
	game = new Game();
	game.init();
	ai = new AI();
	//set human player
	var randomNr = Math.floor(Math.random()*game.players.length);
	humanPos = randomNr;
	game.players[randomNr].isHuman = true;
	game.players[randomNr].name = "You";
	game.players[randomNr].money = 100;
	randomNr = Math.floor(Math.random()*game.players.length);
	game.dealer = game.players[randomNr];
	game.start(PREFLOPGAME);
	for (var i = 0; i < game.players.length; i++){
		//console.log(game.players[i].getPlayerHand());
		updatePlayerDetails(game.players[i]);
	}
	

	
}
function Game(){
	this.init = init;
	this.stop = stop;
	this.dealHands = dealHands;
	this.dealFlop = dealFlop;
	this.dealTurn = dealTurn;
	this.dealRiver = dealRiver;
	this.players= [];
	this.cCards = [];//short for communityCards
	this.start = start;
	this.deck = new Deck();
	this.currentPlayers = [];
	this.currentPlayersUnordered = [];
	this.allInPlayers = [];
	this.maxBets = 4;
	this.dealer = 0;
	
	this.smallBlind = 5;
	this.bigBlind = 10;
	this.maxBetAmount = this.bigBlind;
	this.playersBets = [];
	this.activePlayer;
	this.pot = 0;
	this.betCounter = 0;
	this.lastPlayerToAct;
	this.addBlinds = addBlinds;
	this.winnerIs = winnerIs;
	this.resetRoundBets = resetRoundBets;
	this.sbPlayer;
	this.bbPlayer;
	this.updateButtons = updateButtons;
	this.resetAllInPlayers = resetAllInPlayers;
	this.endRound = endRound;
	this.getAvailableActions = getAvailableActions;
	this.updateUI = updateUI;
	this.findWinner = findWinner;
}

// meetod mängijate loomiseks
function init(){
	for (var i = 0; i < 9; i++){
		this.players.push(new Player(i,PLAYERNAMES[Math.floor(Math.random()*PLAYERNAMES.length)],100));
		//this.players[i].isHuman = true;
	}
	this.playersBets = new Array(this.players.length);
}

// meetod boti tegevuste peatamiseks
function stop(){
	for ( var i = 0; i < this.players.length; i++) { // peatame botid
		this.players[i].isHuman = true;
	}
}
// meetod mängufaasi alustamiseks
function start(gamePhase){
	this.betCounter = 0;
	
	switch(gamePhase)
	{
	case (PREFLOPGAME):
		moveDealerButton(this.dealer.id)
		this.deck = new Deck();
		this.players = this.players.slice(this.players.indexOf(this.dealer)+1,this.players.lenght).concat(this.players.slice(0,this.players.indexOf(this.dealer)+1));//
		this.currentPlayers = this.players.slice(0);
		this.currentPlayersUnordered = this.players.slice(0);
		this.lastPlayerToAct = this.currentPlayers[1];
		this.maxBetAmount = this.bigBlind;
		this.resetRoundBets();
		this.cCards = [];
		this.currentPlayers = this.currentPlayers.slice(2,this.players.lenght).concat(this.currentPlayers.slice(0,2));//
		this.activePlayer = this.currentPlayers[0];
		this.resetAllInPlayers();
		updateActivePlayer(this.activePlayer.id);
		this.dealHands();
		console.log("");
		console.log("Preflop: " + "(Pot: " + (this.pot + this.smallBlind + this.bigBlind) + ")");
		this.addBlinds();
		if (!this.activePlayer.isHuman){
			setTimeout("ai.getAction(game.activePlayer)",3000);
		}
		changeCheckToCallButton();
		restoreRaiseButton();
		this.maxBets = 4;
		NEXTPHASE = FLOPGAME;
		
	break;
	
	case (FLOPGAME):
		changeCallToCheckButton();
		this.currentPlayers = this.currentPlayersUnordered.slice(0);
		this.activePlayer = this.currentPlayers[0];
		this.lastPlayerToAct = this.currentPlayers[this.currentPlayers.length-1];
		this.dealFlop();
		this.resetRoundBets();
		removeAllBets(this.players);
		NEXTPHASE = TURNGAME;
	break;
	
	case (TURNGAME):
		changeCallToCheckButton();
		this.currentPlayers = this.currentPlayersUnordered.slice(0);
		this.activePlayer = this.currentPlayers[0];
		this.lastPlayerToAct = this.currentPlayers[this.currentPlayers.length-1];
		this.dealTurn();
		this.resetRoundBets();
		removeAllBets(this.players);
		this.maxBetAmount = 2*this.bigBlind;
		NEXTPHASE = RIVERGAME;
	break;
	
	case (RIVERGAME):
		this.currentPlayers = this.currentPlayersUnordered.slice(0);
		this.activePlayer = this.currentPlayers[0];
		this.lastPlayerToAct = this.currentPlayers[this.currentPlayers.length-1];
		this.dealRiver();
		this.resetRoundBets();
		removeAllBets(this.players);
		this.maxBetAmount = 2*this.bigBlind;
		NEXTPHASE = SHOWDOWN;
	break;
	
	case (SHOWDOWN):
		for (var i= 0; i < this.currentPlayers.length; i++){
			showPlayerHand(this.currentPlayers[i]);
		}
		for ( var i = 0;  i < this.allInPlayers.length; i++) {
			showPlayerHand(this.allInPlayers[i]);
		}
		showPlayerButtons(false);
		NEXTPHASE = PREFLOPGAME;
		this.findWinner();
		
	break;
	
	}
	if (game.currentPlayers.length > 0){
		this.updateButtons();
	}
	
}


function dealHands(){
	for (var h = 0; h < 2; h++){
		for (var i = 0; i < this.players.length; i++){
			this.players[i].hand.cards[h] = this.deck.giveCard();
		}
	}
	console.log("");
	console.log("Table info: ");
	for (var i = 0; i < this.players.length; i++){
		var info = "";
		if (this.players[i] == this.dealer){
			info = " Dealer";
		}
		if (this.players[i] == this.sbPlayer){
			info += " Small Blind";
		}
		if (this.players[i] == this.bbPlayer){
			info += " Big Blind";
		}
		console.log(this.players[i].name + ": " + this.players[i].money + "€; " + info + "\r\n" + this.players[i].getPlayerHand());
	}
	animateDealingOfCards(0, 1, this.players);
}

function dealFlop(){
	this.deck.giveCard(); // kaart maha
	console.log("");
	console.log("Flop: " + "(Pot: " + this.pot + ")");
	var cards = "";
	for ( var int = 0; int < 3; int++) {
		var card = this.deck.giveCard();
		this.cCards.push(card);
		cards += card.getCardName() + " ";
	}
	console.log(cards);
	animateDealingOfFlop();
}

function dealTurn(){
	this.deck.giveCard(); // kaart maha
	console.log("");
	console.log("Turn: " + "(Pot: " + this.pot + ")");
	var card = this.deck.giveCard();
	this.cCards.push(card);
	console.log(card.getCardName());
	animateDealingOfTurn();
}

function dealRiver(){
	this.deck.giveCard();// kaart maha
	console.log("");
	console.log("River: " + "(Pot: " + this.pot + ")");
	var card = this.deck.giveCard();
	this.cCards.push(card);
	console.log(card.getCardName());
	animateDealingOfRiver();
}

function addBlinds(){
	// adding small blind
	this.sbPlayer = this.players[0];
	this.bbPlayer = this.players[1];
	this.sbPlayer.bet = this.smallBlind;
	this.sbPlayer.money -= this.smallBlind;
	if (this.sbPlayer.money == 0){
		this.currentPlayers.splice(this.currentPlayers.indexOf(this.sbPlayer),1);//
		this.currentPlayersUnordered.splice(this.currentPlayersUnordered.indexOf(this.sbPlayer),1);//
		this.sbPlayer.goAllIn(this.smallBlind);
		this.activePlayer = this.currentPlayers[0]; // juhuks, kui heads up ning SB läheb preflop blindiga ALLIN siis bb action
	}
	this.playersBets[this.sbPlayer.id] += this.smallBlind;
	this.pot += this.smallBlind;
	addPlayerBet(this.sbPlayer,this.smallBlind);
	
	// adding big blind
	var bb;
	if (this.bbPlayer.money < this.bigBlind){
		bb = this.bbPlayer.money;
	}
	else {
		bb = this.bigBlind;
	}
	this.betCounter += 1;
	this.bbPlayer.bet = bb;
	this.bbPlayer.money -= bb;
	if (this.bbPlayer.money == 0){
		this.currentPlayers.splice(this.currentPlayers.indexOf(this.bbPlayer),1);
		this.currentPlayersUnordered.splice(this.currentPlayersUnordered.indexOf(this.bbPlayer),1);
		this.bbPlayer.goAllIn(bb);
		if (!this.sbPlayer.isAllIn){
			this.lastPlayerToAct = this.sbPlayer;
		}
		else {
			this.lastPlayerToAct = this.dealer;
		}
	}
	this.playersBets[this.bbPlayer.id] += bb;
	this.pot += bb;
	addPlayerBet(this.bbPlayer,bb);
	updatePlayerDetails(this.sbPlayer);
	updatePlayerDetails(this.bbPlayer);
}
function findWinner(){
	equalPlayers = []; // siin hoiame mängijaid, kellel hand value on sama
	var maxValue = 0;
	// vaatame läbi aktiivsete mängijate järjendi, ning otsime kõrgeima value'ga kätt
	for ( var i = 0; i < game.currentPlayers.length; i++) {
		var value = game.currentPlayers[i].hand.getValue();
		if (value > maxValue){
			equalPlayers = [];
			equalPlayers.push(game.currentPlayers[i]);
			maxValue = value;
		}
		else if (value == maxValue){
			equalPlayers.push(game.currentPlayers[i]);
		}
	}
	// ja vaatame läbi ALLIN mängijate järjendi
	for ( var i = 0; i < game.allInPlayers.length; i++) {
		var value = game.allInPlayers[i].hand.getValue();
		if (value > maxValue){
			equalPlayers = [];
			equalPlayers.push(game.allInPlayers[i]);
			maxValue = value;
		}
		else if (value == maxValue){
			equalPlayers.push(game.allInPlayers[i]);
		}
	}
	
	//juhul, kui hand valued on sama, leiame paremad käed (kõrgem paar, parem rida, jne)
	winners = equalPlayers.slice(0);
	if (equalPlayers.length > 1){
		winners = [];
		var best = equalPlayers[0].hand.getHand();
		winners.push(equalPlayers[0]);
		for (var i = 1; i < equalPlayers.length; i++) {
			console.log(equalPlayers[i].name + ": " + equalPlayers[i].hand.getCards());
			var result = gaga.compareHands(best,equalPlayers[i].hand.getHand());
			if (result === -1){
				winners = [];
				winners.push(equalPlayers[i]);
				best = equalPlayers[i].hand.getHand();
			}
			else if (result === 0){
				winners.push(equalPlayers[i]);
			}
		}
	}
	game.winnerIs(winners);
}

// meetod võitja kuvamiseks jms operatsioonide tegemiseks
function winnerIs(winners){
	if (NEXTPHASE == PREFLOPGAME){
		// võitja tuli showdownist
		if (winners.length == 1){
			winners[0].money += this.pot;
			var message = winners[0].name + " won the pot("+this.pot+"€) with " + winners[0].hand.getName() + " (" + winners[0].hand.getCards()+ ")";
			console.log(message);
			sendToChat("Dealer",message);
			winners[0].action = WINNER;
			updatePlayerDetails(winners[0]);
		}
		else if (winners.length > 1){
			// split pot
			// TODO: sidepotid
			var winnerNames = "";
			for ( var i = 0; i < winners.length; i++) {
				winners[i].money += this.pot / winners.length;
				winners[i].action = WINNER;
				updatePlayerDetails(winners[i]);
				winnerNames += winners[i].name + ", ";
			}
			var message = "Split pot between " + winnerNames + " each won ("+(this.pot / winners.length)+"€) with " + winners[0].hand.getName() + " (" + winners[0].hand.getCards()+ ")";
			console.log(message);
			sendToChat("Dealer",message);
		}
		else {
			alert ("oh noes.");
		}
	}
	else{ //võitja ei ole showdownist
		var message = winners[0].name + " won the pot("+this.pot+"€)";
		sendToChat("Dealer",message);
		console.log(message);
		winners[0].action = WINNER;
		winners[0].money += this.pot;
		updatePlayerDetails(winners[0]);
	}
	this.pot = 0;
	NEXTPHASE = PREFLOPGAME; //sest kui ilma showdownita kutsutakse meetod välja, siis vaja prefloppi järgmiseks roundiks
	setTimeout("game.endRound()",SHOWDOWLENGTH );
	//game.endRound();
	if (this.players.length > 1){
		setTimeout("game.start("+NEXTPHASE+")",SHOWDOWLENGTH+1000);
		this.updateUI;
		setTimeout("hideCCards()",SHOWDOWLENGTH );
	}
	else {
		alert(winners[0].name + " won!");
	}
}

function resetRoundBets(){
	for ( var int = 0; int < this.playersBets.length; int++) {
		this.playersBets[int] = 0;
	}
}
// tagastab võimalikud käigud järjendina, et botid oskaksid otsustada
function getAvailableActions(){
	actions = [];
	if (this.playersBets.max() - this.playersBets[this.activePlayer.id] > 0){
		actions.push(CALL);
	}
	else {
		actions.push(CHECK);
	}
	if (this.betCounter < 4 && (this.playersBets.max() + this.maxBetAmount - this.playersBets[this.activePlayer.id]) >= this.activePlayer.money){
		actions.push(ALLIN);
	}
	else{
		actions.push(RAISE);
	}
	if ((this.currentPlayers.length == 1 && this.allInPlayers.length >= 1) || this.betCounter >= 4){
		actions.splice(actions.indexOf(RAISE),1);
	}
	if (actions.indexOf(CHECK) == -1){
		actions.push(FOLD);
	}
	if (actions.length == 1  && NEXTPHASE != FLOPGAME){ 
		// mängija saab ainult checkida, st. mäng läheb showdowni
		// selleks, et botid ei saaks sel ajal enam tegutseda, lisame actions järjendisse -1
		actions = [-1];
	}
	return actions;
}
// uuenda mängijale kuvatavate nuppude labelid vastavalt võimalikele tegevustele
function updateButtons(){
	if (this.playersBets.max() - this.playersBets[this.activePlayer.id] > 0){
		changeCheckToCallButton();
	}
	else {
		changeCallToCheckButton();
	}
	if (this.playersBets.max() - this.playersBets[this.activePlayer.id] >= this.activePlayer.money){
		changeCallToAllInButton();
	}
	if (this.betCounter < 4 && (this.playersBets.max() + this.maxBetAmount - this.playersBets[this.activePlayer.id]) >= this.activePlayer.money){
		changeRaiseToAllInButton();
	} else {
		restoreRaiseButton();
	}
	if (this.betCounter >= 4){
		disableRaiseButton();
	}
	else {
		if (this.currentPlayers.length == 1 && this.allInPlayers.length >= 1){
			disableRaiseButton();
		}
		else {
			enableRaiseButton();
		}
	}
	
	showPlayerButtons(this.activePlayer.isHuman);
}

function resetAllInPlayers(){
	this.allInPlayers = [];
	for ( var int = 0; int < this.players.length; int++) {
		this.players[int].isAllIn = false;
	}
}

function endRound(){
	// reset variables and do preparations for next hand
	var tmpPlayers = this.players.slice(0);
	removeAllBets(this.players);
	for ( var int = 0; int < this.players.length; int++) {
		this.players[int].hand = new Hand();
		var tmpPlayer = this.players[int];
		hidePlayerCards(tmpPlayer.id);
		tmpPlayer.action = -1;
		if (tmpPlayer.money == 0){ // eemaldame mängijad, kellel raha otsas
			tmpPlayers.splice(tmpPlayers.indexOf(tmpPlayer),1);
			console.log(tmpPlayer.name + " is broke.");
			sendToChat("Dealer",tmpPlayer.name + " is broke.");
		}
	}
	this.players = tmpPlayers;
	this.dealer = this.players[0];
}

function updateUI(){
	if (this.currentPlayers.length > 0){
		updateActivePlayer(this.activePlayer.id);
		this.updateButtons();
	}
}